-module(pt).
-export([
            read_string/1,
			read_int/1,
			read_short/1,
			read_byte/1,
			read_bytes/1,
			read_tuple/2,
			read_list/2,
			add_string/2,
			add_int/3,
			pack_card_info/1,
			pack_room_info/12,
			read_int_list/1,
			pack_card_list/1,
			pack_end_card_info/1,
			pack_int_list/1,
			pack_guild_info/1,
			pack_ask_list/1,
			pack_club_member_info/1,
			pack_rebate_list/1,
			pack_benifit_list/1,
			pack_inter_record/1,
			pack_inter_update/1,
            pack/2,
			pack/3,
			send/3
			
        ]).
-include("common.hrl").

%%
read_string(Bin) ->
%% 	?debug("BIN=~p",[Bin]),
    case Bin of
        <<Len:16, Bin1/binary>> ->
            case Bin1 of
                <<Str:Len/binary-unit:8, Rest/binary>> ->
                    {binary_to_list(Str), Rest};
                _R1 ->
                    {[],<<>>}
            end;
        _R1 ->
            {[],<<>>}
    end.

read_bytes(Bin) ->
    case Bin of
        <<Len:32, Bin1/binary>> ->
%% 			?log("bytes len=~p",[Len]),
            case Bin1 of				
                <<Str:Len/binary-unit:8, Rest/binary>> ->
                    {Str, Rest};
                _R1 ->
                    {<<>>,<<>>}
            end;
        _R1 ->
            {<<>>,<<>>}
    end.

read_int_list(Bin)->
	case pt:read_short(Bin) of
		{Len,Data}->
			read_int_list(Len,Data,[]);
		_->	[]
	end.

read_int_list(0,_Bin,L)->L;			
read_int_list(Num,Bin,L)->
	{Index,Rest}=pt:read_int(Bin),
	read_int_list(Num-1,Rest,L++[Index]).
%%
read_int(Bin) ->
    case Bin of
        <<Data:32, Rest/binary>> ->
            {Data, Rest};
        _R1 ->
            {-1,<<>>}
    end.

read_short(Bin) ->
	case Bin of
		<<Data:16, Rest/binary>> ->
			{Data, Rest};
		_R ->
			{-1, <<>>}
	end.
read_byte(Bin) ->
	case Bin of
		<<Data:8, Rest/binary>> ->
			{Data, Rest};
		_R ->
			{-1, <<>>}
	end.
read_tuple(Bin1, TypeDefs) ->
	F = fun(ReadFunc, {Ret, Bin}) ->
			{Value, BinRest} = ?MODULE:ReadFunc(Bin),
			{[Value|Ret], BinRest}
		end,
	{Ret, Rest} = lists:foldl(F, {[], Bin1}, TypeDefs),
	{list_to_tuple(lists:reverse(Ret)), Rest}.
read_list(Bin, TypeDef) ->
	{Len, Bin1} = pt:read_short(Bin),
	if 
		Len > 0 -> 
			F = fun(_, {List, BinRest1}) ->
					{Value, BinRest2} = 
						case TypeDef of
							{read_tuple, TypeDefs} -> read_tuple(BinRest1, TypeDefs);
							ReadFunc -> ?MODULE:ReadFunc(BinRest1)
						end,
					{ok, {[Value|List], BinRest2}}
				end,
			{ok, {List, BinRest}} = util:for(0, Len-1, F, {[], Bin1}),
			{lists:reverse(List), BinRest};
		true ->
			{[], Bin1}
	end.

add_string(<<>>,Str) ->
	Bin = util:to_binary(Str),
    Len = byte_size(Bin),	
	<<Len:16, Bin/binary>>;
add_string(Arr,Str) ->
	Bin = util:to_binary(Str),
    Len = byte_size(Bin),	
	<<Arr/binary,Len:16, Bin/binary>>.

add_int(<<>>,Data,Len)->
	Bin = util:to_integer(Data),
	L = util:to_integer(Len),
	<<Bin:L>>;
add_int(Arr,Data,Len)->
	Bin = util:to_integer(Data),
	L = util:to_integer(Len),
	<<Arr/binary,Bin:L>>.
pack_int_list(List)->
	F=fun(Int)->
			  <<Int:?u32>> end,
	ListBin = [F(Data) || Data <- List],	
	 Rlen = length(ListBin),
    RB = list_to_binary(ListBin),
    <<Rlen:?u16, RB/binary>>.
pack_rebate_list(List)->
	F=fun(#us_game_record_card{id=Uid,time=Time,name=Name,bet=Bet,rebate=ReBate})->
	B1= <<Time:?u32>>,
	B2=add_string(B1, Name),
	SendReBate=trunc(ReBate*100),
	 <<B2/binary,Uid:?u32,Bet:?u32,SendReBate:?u32>> end,
	ListBin = [F(Data) || Data <- List],	
	 Rlen = length(ListBin),
	?debug("Rlen=~p",[Rlen]),
    RB = list_to_binary(ListBin),
    <<Rlen:?u16, RB/binary>>.

pack_benifit_list(List)->
	F=fun(#us_game_record_benifit{id=Uid,time=Time,name=Name,rebate=ReBate})->
	B1= <<Time:?u32>>,
	B2=add_string(B1, Name),
	 <<B2/binary,Uid:?u32,ReBate:?u32>> end,
	ListBin = [F(Data) || Data <- List],	
	 Rlen = length(ListBin),
	?debug("Rlen=~p",[Rlen]),
    RB = list_to_binary(ListBin),
    <<Rlen:?u16, RB/binary>>.

pack_club_member_info(List)->
	?debug("List=~p",[List]),
	F=fun(#pt_club_member_info{id=Id,name=Name,
							   head=Head,online=Online,
							   integral=Integral,enter_time=Enter_time,
							   game_num=Game_num,last_login_time=Last_login_time})->
			 B1= <<Id:?u32>>,
			 B2=add_string(B1, unicode:characters_to_binary(Name)),
			 <<B2/binary,Head:?u32,Online:?u32,Integral:?u32,Enter_time:?u32,Game_num:?u32,Last_login_time:?u32>>	 end,
	ListBin = [F(Data) || Data <- List],	
	 Rlen = length(ListBin),
	?debug("Rlen=~p",[Rlen]),
    RB = list_to_binary(ListBin),
    <<Rlen:?u16, RB/binary>>.	
				
pack_ask_list(List)->
	F=fun(#pt_enter_club_info{id=Id,head_id=Head,name=Name,state=State})-> 
			 B1= <<Id:?u32>>,
			 Ret=util:to_binary(Name), 
			 B2=add_string(B1, Ret),
			 <<B2/binary,State:?u32,Head:?u32>> end,
		ListBin = [F(Data) || Data <- List],	
	 Rlen = length(ListBin),
    RB = list_to_binary(ListBin),
    <<Rlen:?u16, RB/binary>>.	
pack_guild_info(GuildInfoList)->
	F=fun(PT_GUILD_INFO)->
#pt_guild_info{id=Id,
								name=Name,
								my_open_game=My_open_game,
								online_player_num=Online_player_num,
								all_player_num=All_player_num,
								creater_id=Creater_id,
			   					myreq_state=State,
			   					guild_head=Head,
			   					card=Card,
			  					integer=In
								}=PT_GUILD_INFO,
	?debug("State=~p",[State]),
	B1= <<Id:?u32>>,
	B2= pt:add_string(B1, Name),
	OpenGameBin=pt:pack_int_list(My_open_game),
	<<B2/binary,OpenGameBin/binary,Online_player_num:?u32,All_player_num:?u32,
			Creater_id:?u32,State:?u32,Head:?u32,Card:?u32,In:?u32>> end,
	ListBin = [F(Data) || Data <- GuildInfoList],	
	 Rlen = length(ListBin),
	?debug("Rlen=~p",[Rlen]),
    RB = list_to_binary(ListBin),
    <<Rlen:?u16, RB/binary>>.

send(0,_Cmd,_Data)->skip;
send(Sid,Cmd,Data)->
	{ok,Bin}=pt_game2c:write(Cmd, Data),
	?debug("Sid=~p,Cmd=~p",[Sid,Cmd]),
	?send(Sid,Bin).

pack_end_card_info(CardList)->
	   F=fun({Key,Num,{Index1,Index2},Fail,Vic,CurrenyVic})->
				<<Key:?u32,Num:?u32,Index1:?u32,Index2:?u32,Fail:?u32,Vic:?u32,CurrenyVic:?u32>> end,
	 	List_Bin=[F(N)||N<-CardList],	
		PRlen1=erlang:length(List_Bin),	
		PBin1=list_to_binary(List_Bin),
		 <<PRlen1:?u16,PBin1/binary>>.
pack_card_info(CardInfoList)->
	F=fun({Type,CardList})->
			  F1=fun(#card{col=Corlor,value=Value})->
			  	<<Corlor:?u32,Value:?u32>>
				end,
	   List_Bin=[F1(N)||N<-CardList],	
		PRlen1=erlang:length(List_Bin),	
		PBin1=list_to_binary(List_Bin),
		 <<Type:?u32,PRlen1:?u16,PBin1/binary>>  end,
	    List_card_bin=[F(N)||N<-CardInfoList],
	    PRlen2=erlang:length(List_card_bin),	
		PBin2=list_to_binary(List_card_bin),
	   <<PRlen2:?u16,PBin2/binary>>.
pack_card_list(CardList)->	
		F=fun(#card{col=Corlor,value=Value,index=Index})->
			  	<<Corlor:?u32,Value:?u32,Index:?u32>> end,
	List_Bin=[F(N)||N<-CardList],	
	PRlen1=erlang:length(List_Bin),	
	PBin1=list_to_binary(List_Bin),
	  <<PRlen1:?u16,PBin1/binary>>.

pack_bets(BetsList)->
	F=fun({Type,Bets})->
			  	<<Type:?u32,Bets:?u32>> end,
	List_Bin=[F(N)||N<-BetsList],	
	PRlen1=erlang:length(List_Bin),	
	PBin1=list_to_binary(List_Bin),
	  <<PRlen1:?u16,PBin1/binary>>.

pack_room_info(PlayerInfo,MasterId,MasterHead,MasterName,
			   MasterBets,SelectBets,MultySelectBets,Status,CardInfoList,Timestemp,CurrencyType,Coin)->
			CardBin=pack_card_info(CardInfoList),
			PlayerNum=erlang:length(PlayerInfo),
			SelectBetsBin=pack_bets(SelectBets), %%平倍下注总和
			MultySelectBetsBin=pack_bets(MultySelectBets), %%加倍下注总和
			Bin1 = <<CurrencyType:?u32,Coin:?u32,PlayerNum:?u32,Status:?u32,MasterId:?u32,MasterHead:?u32>>,
			Bin2=pt:add_string(Bin1, MasterName),
			?debug("CurrencyType=~p,Coin=~p",[CurrencyType,Coin]),
			  <<Bin2/binary,MasterBets:?u32,Timestemp:?u32,SelectBetsBin/binary
				,MultySelectBetsBin/binary,CardBin/binary>>.
pack_inter_record(List)->
	F=fun( #pt_club_game_info{time=Time,scene_type=SceneType,scene_id=SceneId,update=End_interger} )->
			  	<<Time:?u32,SceneType:?u32,SceneId:?u32,End_interger:?u32>> end,
	List_Bin=[F(N)||N<-List],	
	PRlen1=erlang:length(List_Bin),	
	PBin1=list_to_binary(List_Bin),
	  <<PRlen1:?u16,PBin1/binary>>.
pack_inter_update(List)->
	F=fun(#us_game_interger_update{time=Time,interger=Interger})->
			  <<Time:?u32,Interger:?u32>> end,
		List_Bin=[F(N)||N<-List],	
	PRlen1=erlang:length(List_Bin),	
	PBin1=list_to_binary(List_Bin),
	  <<PRlen1:?u16,PBin1/binary>>.
pack(Cmd, Data) ->
	?debug("Pack,Cmd=~p",[Cmd]),
	pack(Cmd, 0, Data).
pack(Cmd, _Seq, Data) ->
    L = byte_size(Data) + 6,
    <<L:?u32, Cmd:?u16, Data/binary>>.
